package edu.kufpg.armatus; import android.app.Activity; import android.os.AsyncTask; import java.lang.ref.WeakReference; /** * An {@link AsyncTask} whose execution is intimately connected with an {@link Activity}. Unlike * a regular {@code AsyncTask}, an {@code AsyncActivityTask} can safely interact with its associated * {@code Activity} in the UI thread methods ({@link #onPreExecute()}, {@link #onCancelled()}, {@link * AsyncTask#onProgressUpdate(Progress...) onProgressUpdate(Progress)}, and {@link #onPostExecute(Result)}), * even during or after {@code Activity} rotation or standby. * @param <A> The {@code Activity} class this task is associated with. * @param <Params> The {@code Object} that this task takes as input when calling {@link * AsyncTask#execute(Params...) execute(Params...)}. * @param <Progress> The {@code Object} that this task uses to determine execution progress. * @param <Result> The {@code Object} that this task returns when execution is completed. */ public abstract class AsyncActivityTask<A extends Activity, Params, Progress, Result> extends AsyncTask<Params, Progress, Result> { /** * A reference to the app's {@link android.app.Application Application}, which manages the connection * between this task and its associated {@link Activity}. */ private final BaseApplication mApp; //private final NoGuavaBaseApplication mApp; /** * References this task's associated {@link Activity}. <b>DO NOT</b> access this reference * directly, since there is a chance that it could be set to null due to {@code Activity} * rotation or standby. Instead, use {@link #getActivity()} every time that you want to use the * {@code Activity} to ensure that the correct reference is returned. */ private WeakReference<A> mActivityRef; public AsyncActivityTask(A activity) { mActivityRef = new WeakReference<A>(activity); mApp = (BaseApplication) activity.getApplication(); //mApp = (NoGuavaBaseApplication) activity.getApplication(); } /** * Instead of accessing the connected {@link Activity} directly, use this method to * ensure that the returned {@code Activity} will always be safe to use, regardless * of {@code Activity} rotation or standby. * @return The associated {@code Activity}. */ public A getActivity() { return mActivityRef.get(); } /** * Use this method to reestablish a connection to this task's {@link Activity} after * rotation or standby. * @param activity The {@code Activity} to reconnect to. */ public void attachActivity(A activity) { mActivityRef = new WeakReference<A>(activity); onActivityAttached(); } public void detachActivity() { onActivityDetached(); } /** * Called when this task's {@link android.app.Application Application} restores the * references between the task and its associated {@link Activity}. This is usually called * when rotation completes or when the {@code Activity} comes back into focus after * standby. */ protected void onActivityAttached() {} /** * Called when this task's {@link android.app.Application Application} sets the references * between the task and its associated {@link Activity} to {@code null}. This is usually * called immediately before the {@code Activity} is rotated or put into standby. */ protected void onActivityDetached() {} @Override protected void onPreExecute() { mApp.addTask(getActivity(), this); } @Override protected void onPostExecute(Result result) { mApp.removeTask(getActivity(), this); } /** * Make sure you call {@code super.onCancelled(result)} (contrary to the advice given * in the documentation for {@link AsyncTask}). */ @Override protected void onCancelled(Result result) { mApp.removeTask(getActivity(), this); onCancelled(); } }